/*
 * @Author: rock
 * @Date: 2025-09-30 22:32:00
 * @LastEditors: rock 
 * @LastEditTime: 2025-10-01 17:15:03
 * @FilePath: /Server/include/pack.h
 * @Description: Ctrl+Num1-> For Document; Ctrl+Num2-> For Function
 * 
 * Copyright (c) 2025 by rock, All Rights Reserved. 
 */
#ifndef PACK_H
#define PACK_H

#include <iostream>
#include <cstring>

#define PACK_HEADER '\xaa'
#define PACK_TAIL   '\xbb'

#define LEN_BEGIN       0   /*数据标志位begin*/

#define LEN_HEADER      1   /*header标志位占用的长度*/
#define LEN_LEN         32  /*len标志位占用的char*的长度*/
#define LEN_TOUSER      32  /*touser占用的长度*/
#define LEN_TO_IP       32  /*TO_IP占用的长度*/
#define LEN_TO_PORT     32  /*TO_PORT占用的长度*/
#define LEN_FROMUSER    32  /*fromuser占用的长度*/
#define LEN_FROM_IP     32  /*FROM_IP占用的长度*/
#define LEN_FROM_PORT   32  /*FROM_PORT占用的长度*/
#define LEN_DOWHAT      32  /*dowhat占用的长度*/
#define LEN_TAIL        1   /*tail标志位占用的长度*/

#define PACK_POS01_HEADER     LEN_BEGIN /*从数据起始位置开始, 数据头部位置*/
#define PACK_POS02_LEN        LEN_BEGIN+LEN_HEADER /*数据包长度位置*/
#define PACK_POS03_TOUSER     LEN_BEGIN+LEN_HEADER+LEN_LEN/*数据包touser位置*/
#define PACK_POS04_TO_IP      LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER/**/
#define PACK_POS05_TO_PORT    LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER+LEN_TO_IP/**/
#define PACK_POS06_FROMUSER   LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER+LEN_TO_IP+LEN_TO_PORT/*数据包fromuser位置*/
#define PACK_POS07_FROM_IP    LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER+LEN_TO_IP+LEN_TO_PORT+LEN_FROMUSER
#define PACK_POS08_FROM_PORT  LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER+LEN_TO_IP+LEN_TO_PORT+LEN_FROMUSER+LEN_FROM_IP
#define PACK_POS09_DOWHAT     LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER+LEN_TO_IP+LEN_TO_PORT+LEN_FROMUSER+LEN_FROM_IP+LEN_FROM_PORT/*数据包dowhat位置*/
#define PACK_POS10_PACK         LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER+LEN_TO_IP+LEN_TO_PORT+LEN_FROMUSER+LEN_FROM_IP+LEN_FROM_PORT+LEN_DOWHAT/*数据包pack位置*/
//#define PACK_POS_TAIL       LEN_BEGIN+LEN_HEADER+LEN_LEN+LEN_TOUSER+PACK_POS_FROMUSER+LEN_DOWHAT+LEN_PACK/*数据包tail位置*/

class DataPack
{
public:
    DataPack(){}
    ~DataPack()
    {    
        if(msg!=nullptr)
        {
            delete msg;
            msg = nullptr;
        } 
    }

public:
    char header = PACK_HEADER;          //数据包  头部
    char packLen[LEN_LEN] = {0};        //数据包描述信息, 32字节 
    int lenPack = 0;                    //数据包总长度
    char toUser[LEN_TOUSER] = {0};      //目的user
    char toUserIp[LEN_TO_IP] = {0};     //目的ip是多少
    char toUserPort[LEN_TO_PORT] = {0}; //目的端口号是多少
    char fromUser[LEN_FROMUSER] = {0};  //源User
    char fromIp[LEN_FROM_IP] = {0};     //源ip
    char fromPort[LEN_FROM_PORT] = {0}; //源port
    char doWhat[LEN_DOWHAT] = {0};      //dowhat
    char* msg = nullptr;                //发送的数据
    char msgLen = 0;                    //发送的数据的长度
    char tail = PACK_TAIL;              //数据包  尾部
};



/**
 * @brief Pack
 * 组包
 * @param msg:要封装的消息指针
 * @param msgLen:要封装的消息的长度
 * @return返回一个组装好的数据包指针, 这个指针为new的堆内存
 */
char* Pack(DataPack& destPack)
{
    char* dataPack = nullptr;

    //先计算数据包总长度
    //为整个数据包分配内存
    destPack.lenPack =
        LEN_BEGIN +
        LEN_HEADER +
        LEN_LEN +
        LEN_TOUSER +
        LEN_TO_IP +
        LEN_TO_PORT +
        LEN_FROMUSER +
        LEN_FROM_IP +
        LEN_FROM_PORT +
        LEN_DOWHAT +
        destPack.msgLen +
        LEN_TAIL;
     

    //申请内存
    dataPack  = new char[destPack.lenPack];

    //组包
    //数据包头部
    dataPack[PACK_POS01_HEADER] = PACK_HEADER;    

    //数据包总长度
    memcpy(dataPack+PACK_POS02_LEN, &destPack.lenPack, LEN_LEN);

    //touser
    memcpy(dataPack+PACK_POS03_TOUSER, destPack.toUser, LEN_TOUSER);

    //to_ip
    memcpy(dataPack+PACK_POS04_TO_IP, destPack.toUserIp , LEN_TO_IP);

    //to_port
    memcpy(dataPack+PACK_POS05_TO_PORT, destPack.toUserPort, LEN_TO_PORT);

    //fromuser
    memcpy(dataPack+PACK_POS06_FROMUSER, destPack.fromUser, LEN_FROMUSER);

    //from_ip
    memcpy(dataPack+PACK_POS07_FROM_IP, destPack.fromIp, LEN_FROM_IP);

    //from_port
    memcpy(dataPack+PACK_POS08_FROM_PORT, destPack.fromPort, LEN_FROM_PORT);

    //dowhat
    memcpy(dataPack+PACK_POS09_DOWHAT, destPack.doWhat, LEN_DOWHAT);


    //msg
    memcpy(dataPack+PACK_POS10_PACK, destPack.msg, destPack.msgLen);


    //tail
    dataPack[destPack.lenPack-1] = PACK_TAIL;

    //组好的包返回
    return dataPack;

}



//拆包
/**
 * @brief unPack
 * @param sourcePack
 * @param destPack
 */
void unPack(char* sourcePack, DataPack& destPack)
{

    //如果接收的数据为空, 直接退出
    if(sourcePack == nullptr)
    {
        return;
    }

    //如果接收的数据头部不为数据头部, 退出
    if(sourcePack[PACK_POS01_HEADER] != PACK_HEADER)
    {
        return;
    }
    
    //解析数据包总长度, 把数据包的长度读出来, 为了拿到数据的尾部, 拿到数据尾部便可以获取到整个数据包是不是对的
    memcpy(&(destPack.lenPack), sourcePack+PACK_POS02_LEN, LEN_LEN);

    //判断尾部
    if(sourcePack[destPack.lenPack-1] != PACK_TAIL)
    {
        printf("%x\n", sourcePack[destPack.lenPack-1]);
        return;
    }
    //数据尾部判断好以后就可以拆分数据了
    //拆分数据头部
    destPack.header = PACK_HEADER;         

    //touser
    memcpy(destPack.toUser, sourcePack+PACK_POS03_TOUSER, LEN_TOUSER);

    //toUserIp
    memcpy(destPack.toUserIp, sourcePack+PACK_POS04_TO_IP, LEN_TO_IP);

    //toUserPort
    memcpy(destPack.toUserPort, sourcePack+PACK_POS05_TO_PORT, LEN_TO_PORT);

    //fromUser
    memcpy(destPack.fromUser, sourcePack+PACK_POS06_FROMUSER, LEN_FROMUSER);

    //fromUserIP
    memcpy(destPack.fromIp, sourcePack+PACK_POS07_FROM_IP, LEN_FROM_IP);

    //fromUserPort
    memcpy(destPack.fromPort, sourcePack+PACK_POS08_FROM_PORT, LEN_FROM_PORT);

    //dowhat
    memcpy(destPack.doWhat, sourcePack+PACK_POS09_DOWHAT, LEN_DOWHAT);

    //msg
    destPack.msgLen = destPack.lenPack -
                      LEN_HEADER -
                      LEN_LEN -
                      LEN_TOUSER -
                      LEN_TO_IP -
                      LEN_TO_PORT -
                      LEN_FROMUSER -
                      LEN_FROM_IP -
                      LEN_FROM_PORT -
                      LEN_DOWHAT -
                      LEN_TAIL      ;
    //为接收的数据做准备
    destPack.msg = new char[destPack.msgLen];
    memcpy(destPack.msg, sourcePack+PACK_POS10_PACK, destPack.msgLen);

    // 封装尾部
    destPack.tail = PACK_TAIL;

}



#endif // PACK_H
